﻿/**************************************************************
 *
 * 唯一标识：edcc24ef-9f89-4d24-986e-6672c14a77f2
 * 命名空间：Sgr.Trackers
 * 创建时间：2024/7/20 20:10:51
 * 机器名称：DESKTOP-HJ4OAG9
 * 创建者：CocoYuan
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using Microsoft.Extensions.Logging;
using Sgr.DistributedLock;
using Sgr.Generator;
using Sgr.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using StackExchange.Redis;

namespace Sgr.Trackers
{
    public class MessageMarkByRedis : IMessageMark
    {
        private readonly IRedisDatabaseContext _redisDatabaseContext;
        private readonly ILogger _logger;

        private const string LOCK_VALUE = "MessageMark";

        public MessageMarkByRedis(
            IRedisDatabaseContext redisDatabaseContext,
            ILogger<RedisDistributedLock> logger)
        {
            _redisDatabaseContext = redisDatabaseContext;
            _logger = logger;
        }

        /// <summary>
        /// 将消息其标记为已执行（注意此处应该是原子操作）
        /// </summary>
        /// <param name="msgId">消息标识</param>
        /// <param name="effectiveSecond">有效期，单位秒（默认7天）</param>
        /// <param name="token"></param>
        /// <returns>消息在此之前已被标记 或者 标记失败 返回False</returns>
        public async Task<bool> MarkAsProcessedAsync(string msgId, int effectiveSecond = 604800, CancellationToken token = default)
        {
            var redisDatabase = await _redisDatabaseContext.ConnectAsync();
            if (redisDatabase == null)
            {
                _logger.LogError("将消息其标记为已执行失败,无法获取Redis连接!");
                return false;
            }

            bool result = false;
            try
            {
                result = await redisDatabase.LockTakeAsync(getKey(msgId), LOCK_VALUE, TimeSpan.FromSeconds(effectiveSecond));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "颁发令牌失败,调用 LockTakeAsync 异常！");
                _redisDatabaseContext.OnRedisError(ex, redisDatabase);
            }

            return result;
        }

        /// <summary>
        /// 删除消息已执行的标记
        /// </summary>
        /// <param name="msgId"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task RemoveAsync(string msgId, CancellationToken token = default)
        {
            var redisDatabase = await _redisDatabaseContext.ConnectAsync();
            try
            {
                await redisDatabase.LockReleaseAsync(getKey(msgId), LOCK_VALUE);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证令牌失败,调用 LockReleaseAsync 异常！");
                _redisDatabaseContext.OnRedisError(ex, redisDatabase);
            }
        }

        private RedisKey getKey(string key)
        {
            return _redisDatabaseContext.InstancePrefix.Append(".m.mark.").Append(key);
        }
    }
}